package com.skyyan.netty.jjf.server;

import com.skyyan.netty.jjf.protocol.*;
import com.skyyan.netty.jjf.util.Str2HexUtils;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 服务端业务逻辑处理器
 * 负责处理与客户端的通信逻辑，包括注册、心跳、业务响应等
 *
 * @author skyyan
 */
public class ServerHandler extends SimpleChannelInboundHandler<Message> {

    private static final Logger log = LoggerFactory.getLogger(ServerHandler.class);

    // 存储已注册的客户端信息
    private static final Map<String, ClientInfo> registeredClients = new ConcurrentHashMap<>();

    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        log.info("客户端连接: {}", ctx.channel().remoteAddress());
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) {
        log.info("客户端断开连接: {}", ctx.channel().remoteAddress());
        // 移除断开连接的客户端
        registeredClients.values().removeIf(clientInfo -> clientInfo.getChannel() == ctx.channel());
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Message msg) throws Exception {
        log.debug("收到客户端消息: {}", msg);

        // 根据消息类型进行处理
        if (msg instanceof RegisterMessage.Uplink) {
            handleRegisterMessage(ctx, (RegisterMessage.Uplink) msg);
        } else if (msg instanceof RegisterConfirmMessage.Uplink) {
            handleRegisterConfirmMessage(ctx, (RegisterConfirmMessage.Uplink) msg);
        } else if (msg instanceof BalanceQueryMessage.Uplink) {
            handleBalanceQueryMessage(ctx, (BalanceQueryMessage.Uplink) msg);
        } else if (msg instanceof RechargeMessage.Uplink) {
            handleRechargeMessage(ctx, (RechargeMessage.Uplink) msg);
        } else if (msg instanceof OpenCardMessage.Uplink) {
            handleOpenCardMessage(ctx, (OpenCardMessage.Uplink) msg);
        } else if (msg instanceof WaterElectricityPriceQueryMessage.Uplink) {
            handleWaterElectricityPriceQueryMessage(ctx, (WaterElectricityPriceQueryMessage.Uplink) msg);
        } else {
            log.warn("未知消息类型: {}", msg.getClass().getName());
        }
    }

    /**
     * 处理注册消息
     *
     * @param ctx 上下文
     * @param msg 注册消息
     */
    private void handleRegisterMessage(ChannelHandlerContext ctx, RegisterMessage.Uplink msg) {
        log.info("处理注册消息");

        // 创建注册响应消息
        RegisterMessage.Downlink ackMsg = new RegisterMessage.Downlink(
                new byte[]{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
                        0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10} // 16字节设备注册号（示例）
        );

        // 发送注册响应
        ctx.writeAndFlush(ackMsg);

        // 保存客户端信息
        String clientKey = Str2HexUtils.bytesToHex(new byte[]{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
                0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10}); // 示例设备注册号
        registeredClients.put(clientKey, new ClientInfo(clientKey, ctx.channel()));
        log.info("客户端注册成功: {}", clientKey);
    }

    /**
     * 处理注册确认消息
     *
     * @param ctx 上下文
     * @param msg 注册确认消息
     */
    private void handleRegisterConfirmMessage(ChannelHandlerContext ctx, RegisterConfirmMessage.Uplink msg) {
        log.info("处理注册确认消息");

        // 创建注册确认响应消息
        RegisterConfirmMessage.Downlink ackMsg = new RegisterConfirmMessage.Downlink(
                (byte) 0x00 // 0x00表示注册成功
        );

        // 发送注册确认响应
        ctx.writeAndFlush(ackMsg);
        log.info("注册确认完成");
    }

    /**
     * 处理余额查询消息
     *
     * @param ctx 上下文
     * @param msg 余额查询消息
     */
    private void handleBalanceQueryMessage(ChannelHandlerContext ctx, BalanceQueryMessage.Uplink msg) {
        log.info("处理余额查询消息");

        try {
            // 创建余额查询响应消息
            BalanceQueryMessage.Downlink responseMsg = new BalanceQueryMessage.Downlink(
                    (byte) 0x00, // 状态码 0x00表示启用
                    10000, // 余额（单位：分）
                    "张三", // 用户名
                    "12345" // 卡号
            );

            // 发送响应
            ctx.writeAndFlush(responseMsg);
        } catch (Exception e) {
            log.error("处理余额查询消息时发生异常", e);
        }
    }

    /**
     * 处理充值消息
     *
     * @param ctx 上下文
     * @param msg 充值消息
     */
    private void handleRechargeMessage(ChannelHandlerContext ctx, RechargeMessage.Uplink msg) {
        log.info("处理充值消息: 充值金额={}分, 订单号={}", msg.getRechargeAmount(), msg.getOrderId());

        try {
            // 创建充值确认消息
            RechargeMessage.Downlink responseMsg = new RechargeMessage.Downlink(
                    (byte) 0x00, // 状态码 0x00表示成功
                    15000, // 余额（单位：分）
                    "张三", // 用户名
                    msg.getOrderId() // 订单号
            );

            // 发送响应
            ctx.writeAndFlush(responseMsg);
        } catch (Exception e) {
            log.error("处理充值消息时发生异常", e);
        }
    }

    /**
     * 处理开卡消息
     *
     * @param ctx 上下文
     * @param msg 开卡消息
     */
    private void handleOpenCardMessage(ChannelHandlerContext ctx, OpenCardMessage.Uplink msg) {
        log.info("处理开卡消息: 姓名={}", msg.getName());
        msg.toString();
        try {
            // 生成随机的16位农户ID
            byte[] farmerId = new byte[16];
            new Random().nextBytes(farmerId);
//            byte[] farmerId = new byte[]{
//                    (byte) 0x11, (byte) 0x22, (byte) 0x33, (byte) 0x44, (byte) 0x55,
//                    (byte) 0x66, (byte) 0x77, (byte) 0x88, (byte) 0x11, (byte) 0x22,
//                    (byte) 0x33, (byte) 0x44, (byte) 0x55, (byte) 0x66, (byte) 0x77,
//                    (byte) 0x88
//            };
            byte[] address=null;
            // 创建开卡响应消息
            OpenCardMessage.Downlink responseMsg = new OpenCardMessage.Downlink(
                    address, // 地址域
                    msg.getOrderId(), // 订单号
                    farmerId, // 随机生成的16位农户ID
                    (byte) 0x00 // 状态码 0x00表示成功
            );

            // 发送响应
            ctx.writeAndFlush(responseMsg);
        } catch (Exception e) {
            log.error("处理开卡消息时发生异常", e);
        }
    }

    /**
     * 处理阶梯水电价查询消息
     *
     * @param ctx 上下文
     * @param msg 阶梯水电价查询消息
     */
    private void handleWaterElectricityPriceQueryMessage(ChannelHandlerContext ctx, WaterElectricityPriceQueryMessage.Uplink msg) {
        log.info("处理阶梯水电价查询消息");

        try {
            // 创建阶梯水电价查询响应消息
            WaterElectricityPriceQueryMessage.Downlink responseMsg = new WaterElectricityPriceQueryMessage.Downlink(
                    (byte) 0x00, // 状态码 0x00表示成功
                    new byte[]{0x12, 0x00, 0x00}, // 水价1（单位：厘）
                    new byte[]{0x3A, 0x00, 0x00}, // 水价2（单位：厘）
                    new byte[]{0x3B, 0x00, 0x00}, // 水价3（单位：厘）
                    new byte[]{0x3C, 0x00, 0x00}, // 电价1（单位：厘）
                    new byte[]{0x3D, 0x00, 0x00}, // 电价2（单位：厘）
                    new byte[]{0x3A, 0x00, 0x00}  // 电价3（单位：厘）
            );

            // 发送响应
            ctx.writeAndFlush(responseMsg);
        } catch (Exception e) {
            log.error("处理阶梯水电价查询消息时发生异常", e);
        }
    }



//    @Override
//    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
//        if (evt instanceof IdleStateEvent) {
//            IdleStateEvent event = (IdleStateEvent) evt;
//            if (event.state() == IdleState.READER_IDLE) {
//                log.info("读超时，客户端: {}", ctx.channel().remoteAddress());
//                ctx.close();
//            } else if (event.state() == IdleState.WRITER_IDLE) {
//                log.debug("写超时，发送心跳消息，客户端: {}", ctx.channel().remoteAddress());
//                // 发送心跳消息
////                ctx.writeAndFlush(HeartbeatMessage.createDownlink(new byte[9]));
//            } else if (event.state() == IdleState.ALL_IDLE) {
//                log.info("总超时，客户端: {}", ctx.channel().remoteAddress());
//                ctx.close();
//            }
//        }
//        super.userEventTriggered(ctx, evt);
//    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        log.error("服务端处理异常", cause);
        ctx.close();
    }
}
